package datastore.db;

import java.util.Iterator;
import java.util.List;

public class BaseQuery<M extends Model> implements Iterable<M> {
    private Class<M> modelClass;
    
    private int offset = 0;
    private int limit = Integer.MAX_VALUE;

    protected BaseQuery(Class<M> modelClass) {
        this.modelClass = modelClass;
    }

    /**
     * Executes the query, then returns the results.
     * 
     * The limit and offset arguments control how many results are fetched from the datastore, and how many are returned
     * by the fetch() method: o The datastore fetches offset + limit results to the application. The first offset
     * results are not skipped by the datastore itself. o The fetch() method skips the first offset results, then
     * returns the rest (limit results). o The query has performance characteristics that correspond linearly with the
     * offset amount plus the limit.
     * 
     * Note: fetch() returns a maximum of 1000 results. If more than 1000 entities match the query, and either no limit
     * is specified or a limit larger than 1000 is used, only the first 1000 results are returned by fetch().
     * 
     * @param limit
     *            The number of results to return. Fewer than limit results may be returned if not enough results are
     *            available that meet the criteria. limit is a required argument. To get every result from a query when
     *            the number of results is unknown, use the Query object as an iterable instead of using the fetch()
     *            method.
     * @param offset
     *            The number of results to skip.
     * @return The return value is a list of model instances, possibly an empty list.
     * @throws Exception 
     */
    public List<M> fetch(int limit, int offset) {
        return Datastore.fetch(this, limit, offset);
    }
    public List<M> fetch(int limit) {
        return fetch(limit, 0);
    }

    /* get()
     * 
     * Executes the query, then returns the first result, or None if the query returned no results.
     * 
     * get() implies a "limit" of 1. At most 1 result is fetched from the datastore.
     */
    public M get() {
        throw new UnsupportedOperationException();
    }

    /* 
     * count(limit)
     * 
     * Returns the number of results this query fetches.
     * count() is somewhat faster than retrieving all of the data by a constant factor, but the running time still grows
     * with the size of the result set. It's best to only use count() in cases where the count is expected to be small,
     * or specify a limit.
     * 
     * Note: count() returns a maximum of 1000. If the actual number of entities that match the query criteria exceeds
     * the maximum, count() returns a count of 1000.
     * 
     * Arguments:
     * 
     * limit
     * 
     * The maximum number of results to count.
     */
    public int count(int limit) {
        throw new UnsupportedOperationException();
    }

    public int count() {
        throw new UnsupportedOperationException();
    }
    
    @Override
    public Iterator<M> iterator() {
        return Datastore.iterable(this, limit, offset).iterator();
    }

    public Class<M> getModelClass() {
        return modelClass;
    }
    
}
